/********************************************************************************
  * @file     SD93F115B_flash.c
  * @author   TEST TEAM 												    	
  * @version  v0															    	
  * @date     Septemper 2022												    	
  * @brief
  *
  * Copyright (C) 2022  Hangzhou SDIC Microelectronics Co., Ltd
**********************************************************************************/

/*****Includes*******/
#include "SD93F115B_flash.h"
 

/*------------------------------------------
 * 函数功能：FLASH解锁
 * 入口参数：
 * 出口参数：
 * 返回值  ：
 * 编写日期：
 * 作者    ：
 *------------------------------------------*/
void FLASH_Unlock(void)
{
	if((FLASH->CR & FLASH_CR_LOCK) != RESET)
	{
		FLASH -> KEYR =	FLASH_KEY1;
	    FLASH -> KEYR =	FLASH_KEY2;
	}

}

/*-----------------------------------------
 * 函数功能：FLASH上锁
 * 入口参数：
 * 出口参数：
 * 返回值  ：
 * 编写日期：
 * 作者    ：
 *----------------------------------------*/ 
void FLASH_Lock(void)
{	
	
	FLASH -> CR	|= FLASH_CR_LOCK;	
}

/*------------------------------------------------
 * 函数功能：FLSAH擦除一个Sector,即512个字节
 * 入口参数：Page_Address
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *-------------------------------------------------*/
FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
{	
	uint32_t tmpreg=0;
    /* Check the parameters */
	assert_param(IS_FLASH_Program_Address(Page_Address));
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁
	FLASH_Status status = FLASH_COMPLETE;	

	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	
	if(status == FLASH_COMPLETE)
	{ 
        FLASH->SR |= FLASH_SR_EOP;
		FLASH->CR |= FLASH_CR_SER;
		FLASH->AR  = Page_Address;
        FLASH->CR |= FLASH_CR_STRT;
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
		if(status==FLASH_COMPLETE)
		{
		status = FLASH_WaitEOPOperation(FLASH_ER_PRG_TIMEOUT);	
		}	
		FLASH->CR &= ~FLASH_CR_SER;
	}
    FLASH_Lock();	 //FLASH上锁
	VIC_ISER = tmpreg;     //将中断使能初赋给VIC使能寄存器
	return status;
}

/*----------------------------------------------
 * 函数功能：擦除120K的主FLSAH区
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------*/
FLASH_Status FLASH_EraseAllPages(void)
{
	uint32_t tmpreg=0;
	FLASH_Status status = FLASH_COMPLETE;
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁	
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);	
	if(status == FLASH_COMPLETE)
	{   
		FLASH->SR |= FLASH_SR_EOP;
		FLASH->CR |= FLASH_CR_MER;
		FLASH->CR |= FLASH_CR_STRT;
	
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
		if(status==FLASH_COMPLETE)
		{
		status = FLASH_WaitEOPOperation(FLASH_ER_PRG_TIMEOUT);	
		}
        	
		FLASH->CR &= ~FLASH_CR_MER;
	}	
	FLASH_Lock();	 //FLASH上锁
    VIC_ISER = tmpreg;     //将中断使能初赋给VIC使能寄存器
	return status;
}

/*------------------------------------------------------
 * 函数功能：等待FLASH操作完成
 * 入口参数：Timeout
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *------------------------------------------------------*/
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
{ 
	FLASH_Status status = FLASH_COMPLETE;	

	status = FLASH_GetStatus();	

	while((status == FLASH_BUSY) && (Timeout != 0x00))
	{
		status = FLASH_GetStatus();
		Timeout--;
	}	
	if(Timeout == 0x00 )
	{
		status = FLASH_TIMEOUT;
	}
	return status;
}
/*------------------------------------------------------
 * 函数功能：等待FLASH EOP完成
 * 入口参数：Timeout
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *------------------------------------------------------*/
FLASH_Status FLASH_WaitEOPOperation(uint32_t Timeout)
{ 
	FLASH_Status status = FLASH_COMPLETE;
	while((FLASH->SR & FLASH_SR_EOP) != FLASH_SR_EOP)
	{
		Timeout--;
	}	
	if(Timeout == 0x00)
	{
		status = FLASH_TIMEOUT;
	}
	FLASH->SR |= FLASH_SR_EOP;
	return status;
}
/*----------------------------------------------------
 * 函数功能：读FLSAH 忙，写保护错误，编程错误标志位
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：FLASHStatus
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------*/
FLASH_Status FLASH_GetStatus(void)
{
	FLASH_Status FLASHStatus = FLASH_COMPLETE;
	
	if((FLASH->SR & FLASH_Flag_BSY) == FLASH_Flag_BSY) 
	{
		FLASHStatus = FLASH_BUSY;
	}
	else 
	{  
		if((FLASH->SR & FLASH_Flag_WRPRTERR)!= 0)
		{ 
			FLASHStatus = FLASH_ERROR_WRP;
		}
		else 
		{
			if((FLASH->SR & (FLASH_Flag_PGERR)) != 0)
			{
				FLASHStatus = FLASH_ERROR_PGERR; 
			}
			else
			{
				FLASHStatus = FLASH_COMPLETE;
			}
		}
		
	}
	return FLASHStatus;
}

/*----------------------------------------------------
 * 函数功能：FLSAH字编程
 * 入口参数：Address，32位Data
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------*/
FLASH_Status FLASH_ProgramWord(uint32_t Address,volatile uint32_t Data)
{
	uint32_t tmpreg=0;
	/* Check the parameters */
	assert_param(IS_FLASH_Program_Address(Address));
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁
	FLASH_Status status = FLASH_COMPLETE;		

	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);	
	if(status == FLASH_COMPLETE)
	{
		FLASH->SR |= FLASH_SR_EOP;
		FLASH->CR |= FLASH_CR_PG;
		*(__IO uint32_t*)Address = (uint32_t)Data;	
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
		if(status==FLASH_COMPLETE)
		{
		status = FLASH_WaitEOPOperation(FLASH_ER_PRG_TIMEOUT);	
		}
		FLASH->CR &= ~FLASH_CR_PG;
	}
	FLASH_Lock();	 //FLASH上锁
	VIC_ISER = tmpreg;     //将中断使能初赋给VIC使能寄存器
	return status;
	
}

/*-----------------------------------------------------------------
 * 函数功能：FLSAH半字编程
 * 入口参数：Address，16位Data
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------------------------*/
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{	
	uint32_t tmpreg=0;
	/* Check the parameters */
	assert_param(IS_FLASH_Program_Address(Address));
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁

	FLASH_Status status = FLASH_COMPLETE;	

	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	
	if(status == FLASH_COMPLETE)
	{
		FLASH->SR |= FLASH_SR_EOP;	
		FLASH->CR |= FLASH_CR_PG;
	
		*(__IO uint16_t*)Address = Data;
	
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
		if(status==FLASH_COMPLETE)
		{
		status = FLASH_WaitEOPOperation(FLASH_ER_PRG_TIMEOUT);	
		}
		FLASH->CR &= ~FLASH_CR_PG;
	} 	
    FLASH_Lock();	 //FLASH上锁
	VIC_ISER = tmpreg;     //将中断使能初赋给VIC使能寄存器
	return status;
}

/*-----------------------------------------------------------------
 * 函数功能：FLSAH字节编程
 * 入口参数：Address，8位Data
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------------------------*/
FLASH_Status FLASH_ProgramByte(uint32_t Page_Address, uint8_t Data)
{	
	uint32_t tmpreg=0;
	/* Check the parameters */
	assert_param(IS_FLASH_Program_Address(Page_Address));
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁

	FLASH_Status status = FLASH_COMPLETE;	

	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	
	if(status == FLASH_COMPLETE)
	{
		FLASH->SR |= FLASH_SR_EOP;	
		FLASH->CR |= FLASH_CR_PG;
	
		*(__IO uint8_t*)Page_Address = Data;
	
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
		if(status==FLASH_COMPLETE)
		{
		status = FLASH_WaitEOPOperation(FLASH_ER_PRG_TIMEOUT);	
		}
		FLASH->CR &= ~FLASH_CR_PG;
	} 
    FLASH_Lock();	 //FLASH上锁
	VIC_ISER = tmpreg;     //将中断使能初赋给VIC使能寄存器	
	return status;
}

/*------------------------------------------------
 * 函数功能：选项字节区解锁
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：None
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------*/
void FLASH_OB_Unlock(void)
{
	if((FLASH->CR & FLASH_CR_OPTWRE) == RESET)
	{ 

		FLASH->OPTKEYR = FLASH_OPTKEY1;
		FLASH->OPTKEYR = FLASH_OPTKEY2;	
	}
}

/*------------------------------------------
 * 函数功能：选项字节区上锁
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：None
 * 编写日期：
 * 作者    ：
 *------------------------------------------*/
void FLASH_OB_Lock(void)
{	
	FLASH->CR &= ~FLASH_CR_OPTWRE;	
}

/*------------------------------------------
 * 函数功能：选项字节数据强制装载，这个操作会引起一次系统复位
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：None
 * 编写日期：
 * 作者    ：
 *-----------------------------------------*/
void FLASH_OB_Launch(void)
{
	FLASH->CR |= FLASH_CR_OBL_LAUNCH;
}
/*-----------------------------------------------------
 * 函数功能：将选项字节恢复出厂设置
 * 入口参数：FLASH_OB_RDP
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------*/
FLASH_Status FLASH_OB_DEFAULT(void)
{  
	/* Check the parameters */
	assert_param(IS_FLASH_OB_RDP(FLASH_OB_RDP));
	uint32_t tmpreg=0;
	FLASH_Status status = FLASH_COMPLETE;
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断	
	status = FLASH_OB_Erase();  //选项字节擦除
	
	FLASH_Unlock();       //FLASH解锁	
	FLASH_OB_Unlock();   //选项字节区解锁
	
	if(status == FLASH_COMPLETE)
		{
		
		    FLASH->CR |= FLASH_CR_OPTPG;
		
		    OB->RDP = (uint16_t)0x9966;
			OB->USER = (uint16_t)0xff00;
			OB->WRP0 = (uint16_t)0x00ff;
			OB->WRP1 = (uint16_t)0x00ff;
			OB->WRP2 = (uint16_t)0x00ff;
			OB->WRP3 = (uint16_t)0x00ff;
		
		    status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); 
		
		    FLASH->CR &= ~FLASH_CR_OPTPG;
        }
 	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status;
  
}
/*--------------------------------------------------
 * 函数功能：使能FLASH写保护
 * 入口参数：FLASH_WRP
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *---------------------------------------------------*/
FLASH_Status FLASH_OB_EnableWRP(uint32_t FLASH_WRP)
{
	/* Check the parameters */
	assert_param(IS_FLASH_WRP(FLASH_WRP));
	uint32_t tmpreg=0;
	uint16_t OBL[6];
	uint16_t WRP0_Data = 0xFFFF, WRP1_Data = 0xFFFF;
	
	uint16_t WRP2_Data = 0xFFFF, WRP3_Data = 0xFFFF;

	FLASH_Status status = FLASH_COMPLETE;
	
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	OBL[0] = OB->USER;   //缓存写保护等数据
	OBL[1] = OB->WRP0;
	OBL[2] = OB->WRP1;
	OBL[3] = OB->WRP2;
	OBL[4] = OB->WRP3;
	OBL[5] = OB->RDP;
	status = FLASH_OB_Erase();  //选项字节擦除
	
	FLASH_Unlock();//FLASH解锁
	FLASH_OB_Unlock();   //选项字节区解锁
	
	FLASH_WRP=(uint32_t)~(FLASH_WRP);
	
	WRP0_Data = (uint16_t)((FLASH_WRP|0xff00) & FLASH_OB_nWRP_WRP);
	
	WRP1_Data = (uint16_t)(((FLASH_WRP>>8)|0xff00) & FLASH_OB_nWRP_WRP);
 
	WRP2_Data = (uint16_t)(((FLASH_WRP>>16)|0xff00)  & FLASH_OB_nWRP_WRP);

	WRP3_Data = (uint16_t)(((FLASH_WRP>>24)|0xff00)  & FLASH_OB_nWRP_WRP);
	
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	
	if(status == FLASH_COMPLETE)
	{
		
	FLASH->CR |= FLASH_CR_OPTPG;	
		    
	FLASH_OB_PGM(&(OB->WRP0),(WRP0_Data&(OBL[1]|0xff00)));
	FLASH_OB_PGM(&(OB->WRP1),(WRP1_Data&(OBL[2]|0xff00)));
	FLASH_OB_PGM(&(OB->WRP2),(WRP2_Data&(OBL[3]|0xff00)));
	FLASH_OB_PGM(&(OB->WRP3),(WRP3_Data&(OBL[4]|0xff00)));
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);		
	FLASH->CR &= ~FLASH_CR_OPTPG;
	}
	FLASH_OB_PGM(&(OB->USER),OBL[0]);  //写入缓存数据
	FLASH_OB_PGM(&(OB->RDP),OBL[5]);  //写入缓存数据
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
    return status;  
}

/*-----------------------------------------------------
 * 函数功能：配置读保护等级
 * 入口参数：FLASH_OB_RDP
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------*/
FLASH_Status FLASH_OB_RDPConfig(uint16_t FLASH_OB_RDP)
{  
	/* Check the parameters */
	assert_param(IS_FLASH_OB_RDP(FLASH_OB_RDP));
	uint32_t tmpreg=0;
	volatile uint16_t OBL[5];
	FLASH_Status status = FLASH_COMPLETE;
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断	
	OBL[0] = OB->USER;   //缓存写保护等数据
	OBL[1] = OB->WRP0;
	OBL[2] = OB->WRP1;
	OBL[3] = OB->WRP2;
	OBL[4] = OB->WRP3;
	status = FLASH_OB_Erase();  //选项字节擦除
	
	FLASH_Unlock();//FLASH解锁	
	FLASH_OB_Unlock();   //选项字节区解锁
	
	if(status == FLASH_COMPLETE)
		{
		
		    FLASH->CR |= FLASH_CR_OPTPG;
		
		    OB->RDP = FLASH_OB_RDP;
		
		    status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); 
		
		    FLASH->CR &= ~FLASH_CR_OPTPG;
        }
     
	FLASH_OB_PGM(&(OB->USER),OBL[0]);  //写入写保护等缓存数据
	FLASH_OB_PGM(&(OB->WRP0),OBL[1]);  
	FLASH_OB_PGM(&(OB->WRP1),OBL[2]);  
	FLASH_OB_PGM(&(OB->WRP2),OBL[3]);  
	FLASH_OB_PGM(&(OB->WRP3),OBL[4]);  
 	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status;
  
}

/*----------------------------------------------------
 * 函数功能：配置看门狗（硬件或软件）
 * 入口参数：OB_User_WDG:OB_User_WDG_SW、OB_User_WDG_nSW  
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------*/
FLASH_Status FLASH_OB_User_WDGConfig(uint16_t OB_User_WDG)
{
	/* Check the parameters */
	assert_param(IS_OB_User_WDG(OB_User_WDG));
	uint32_t tmpreg=0,tmpreg1=0;
	uint16_t OBL[5];
    FLASH_Status status = FLASH_COMPLETE;	
  	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	OBL[0] = OB->RDP;   //缓存写保护等数据
	OBL[1] = OB->WRP0;
	OBL[2] = OB->WRP1;
	OBL[3] = OB->WRP2;
	OBL[4] = OB->WRP3;
	status = FLASH_OB_Erase();  //选项字节擦除
	
	FLASH_Unlock();//FLASH解锁	
	FLASH_OB_Unlock();   //选项字节区解锁
    status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
  
    if(status == FLASH_COMPLETE)
	{
		FLASH->CR |= FLASH_CR_OPTPG;
		
		tmpreg1=0xBFBF & OB->USER;
		
		tmpreg1|=OB_User_WDG<<6;
		OB_User_WDG=~(OB_User_WDG)&0x01;
		tmpreg1|=OB_User_WDG<<14;
		OB->USER = tmpreg1;
		
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); 
		
		FLASH->CR &= ~FLASH_CR_OPTPG;
	}
	FLASH_OB_PGM(&(OB->RDP),OBL[0]);  //写入写保护等缓存数据
	FLASH_OB_PGM(&(OB->WRP0),OBL[1]);
	FLASH_OB_PGM(&(OB->WRP1),OBL[2]);
	FLASH_OB_PGM(&(OB->WRP2),OBL[3]);
	FLASH_OB_PGM(&(OB->WRP3),OBL[4]);    
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status;
}

/*----------------------------------------------------
 * 函数功能：配置低压检测信号有效长度
 * 入口参数：OB_User_BOR_TML
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------*/
FLASH_Status FLASH_OB_User_BOR_TMLConfig(uint16_t OB_User_BOR_TML)
{
	/* Check the parameters */
	assert_param(IS_OB_User_BOR_TML(OB_User_BOR_TML));
	uint32_t tmpreg=0,tmpreg1=0;
	uint16_t OBL[5];
    FLASH_Status status = FLASH_COMPLETE;	
  	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	OBL[0] = OB->RDP;   //缓存写保护等数据
	OBL[1] = OB->WRP0;
	OBL[2] = OB->WRP1;
	OBL[3] = OB->WRP2;
	OBL[4] = OB->WRP3;
	status = FLASH_OB_Erase();  //选项字节擦除
	
	FLASH_Unlock();//FLASH解锁	
	FLASH_OB_Unlock();   //选项字节区解锁
    status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
  
    if(status == FLASH_COMPLETE)
	{
		FLASH->CR |= FLASH_CR_OPTPG;
		
		tmpreg1=0xF0F0 & OB->USER;
		
		tmpreg1|=OB_User_BOR_TML;
		OB_User_BOR_TML=~(OB_User_BOR_TML)&0x0F;
		tmpreg1|=OB_User_BOR_TML<<8;
		OB->USER = tmpreg1;
			
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); 
		
		FLASH->CR &= ~FLASH_CR_OPTPG;
	}
	FLASH_OB_PGM(&(OB->RDP),OBL[0]);  //写入写保护等缓存数据
	FLASH_OB_PGM(&(OB->WRP0),OBL[1]);
	FLASH_OB_PGM(&(OB->WRP1),OBL[2]);
	FLASH_OB_PGM(&(OB->WRP2),OBL[3]);
	FLASH_OB_PGM(&(OB->WRP3),OBL[4]);    
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status;
}

/*----------------------------------------------------
 * 函数功能：配置低压检测阈值
 * 入口参数：OB_User_BOR_VTH
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------*/
FLASH_Status FLASH_OB_User_BOR_VTHConfig(uint16_t OB_User_BOR_VTH)
{
	/* Check the parameters */
	assert_param(IS_OB_User_BOR_VTH(OB_User_BOR_VTH));
	uint32_t tmpreg=0,tmpreg1=0;
	uint16_t OBL[5];
    FLASH_Status status = FLASH_COMPLETE;	
  	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	OBL[0] = OB->RDP;   //缓存写保护等数据
	OBL[1] = OB->WRP0;
	OBL[2] = OB->WRP1;
	OBL[3] = OB->WRP2;
	OBL[4] = OB->WRP3;
	status = FLASH_OB_Erase();  //选项字节擦除
	
	FLASH_Unlock();//FLASH解锁	
	FLASH_OB_Unlock();   //选项字节区解锁
    status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
  
    if(status == FLASH_COMPLETE)
	{
		FLASH->CR |= FLASH_CR_OPTPG;
		
		tmpreg1=0xCFCF & OB->USER;
		
		tmpreg1|=OB_User_BOR_VTH<<4;
		OB_User_BOR_VTH=~(OB_User_BOR_VTH)&0x03;
		tmpreg1|=OB_User_BOR_VTH<<12;
		OB->USER = tmpreg1;
			
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); 
		
		FLASH->CR &= ~FLASH_CR_OPTPG;
	}
	FLASH_OB_PGM(&(OB->RDP),OBL[0]);  //写入写保护等缓存数据
	FLASH_OB_PGM(&(OB->WRP0),OBL[1]);
	FLASH_OB_PGM(&(OB->WRP1),OBL[2]);
	FLASH_OB_PGM(&(OB->WRP2),OBL[3]);
	FLASH_OB_PGM(&(OB->WRP3),OBL[4]);    
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status;
}

/*------------------------------------------
 * 函数功能：选项字节擦除
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *-----------------------------------------*/
FLASH_Status FLASH_OB_Erase(void)
{		
	uint32_t tmpreg=0;
	FLASH_Status status = FLASH_COMPLETE;
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁
	
	FLASH_OB_Unlock();   //选项字节区解锁
	
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	
	if(status == FLASH_COMPLETE)
	{  
		FLASH->CR |= FLASH_CR_OPTER;
		FLASH->CR |= FLASH_CR_STRT;
		
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);

		FLASH->CR &= ~FLASH_CR_OPTER;
	}
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁	
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
    return status;
}
/*------------------------------------------
 * 函数功能：选项字节写入
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *-----------------------------------------*/
void FLASH_OB_PGM( volatile uint16_t * OB_Adress,uint16_t data)
{
	FLASH_Status status = FLASH_COMPLETE;
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	if((status == FLASH_COMPLETE)&& (data!=(uint16_t)0xffff))
		{
			FLASH->CR |= FLASH_CR_OPTPG;
			
		     *(__IO uint16_t*)OB_Adress = (uint16_t)data;
		
		    status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); 

			FLASH->CR &= ~FLASH_CR_OPTPG;
			
		}
}
/*------------------------------------------------
 * 函数功能：获取选项字节用户看门狗配置
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：选项字节用户配置信息
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------*/
uint8_t FLASH_OB_GetWDGConfig(void)
{
	return (uint8_t)(FLASH->OBR>>14);
}
/*------------------------------------------------
 * 函数功能：获取选项字节用户低压检测信号有效长度配置
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：选项字节用户配置信息
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------*/
uint8_t FLASH_OB_GetBOR_TMLConfig(void)
{
	return (uint8_t)((FLASH->OBR>>10)&0x0F);
}

/*------------------------------------------------
 * 函数功能：获取选项字节用户低压检测阈值配置
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：选项字节用户配置信息
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------*/
uint8_t FLASH_OB_GetBOR_VTHConfig(void)
{
	return (uint8_t)((FLASH->OBR>>8)&0x03);
}

/*-----------------------------------------------
 * 函数功能：获取选项字节读保护等级
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：选项字节读保护等级
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------*/
uint8_t FLASH_OB_GetRDP(void)
{
    return (uint8_t)(FLASH->OBR>>1);
}

/*------------------------------------------------
 * 函数功能：获取FLASH写保护状态
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：FLASH写保护状态
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------*/
uint32_t FLASH_OB_GetWRP(void)
{
	return (uint32_t)(FLASH->WRPR);
}

/*------------------------------------------------
 * 函数功能：获取选项字节装载错误标志位
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：readstatus
 * 编写日期：
 * 作者    ：
 *-----------------------------------------------*/
FLASH_Status FLASH_OB_GetLoadERRFlagStatus(void)
{
	FlagStatus readstatus = RESET;
	
	if ((FLASH->OBR & FLASH_OBR_OPTERR) != RESET)
	{
		readstatus = SET;
	}
	else
	{
		readstatus = RESET;
	}
	return readstatus;
}

/*----------------------------------------------------------------
 * 函数功能：擦除用户数据0扇区
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------------------*/
FLASH_Status FLASH_UserData_EraseDT0ER(void)
{
    FLASH_Status status = FLASH_COMPLETE;
    uint32_t tmpreg=0;
	
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁
	
	FLASH_OB_Unlock();   //选项字节区解锁
	if(status == FLASH_COMPLETE)
	{ 

		FLASH->CR |= FLASH_CR_DT0ER;
		FLASH->CR |= FLASH_CR_STRT;	

		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);	

		FLASH->CR &= ~FLASH_CR_DT0ER;
	}
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器	
	return status; 
 
}
/*----------------------------------------------------------------
 * 函数功能：擦除用户数据1扇区
 * 入口参数：None
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------------------*/
FLASH_Status FLASH_UserData_EraseDT1ER(void)
{
	FLASH_Status status = FLASH_COMPLETE;
    uint32_t tmpreg=0;
	
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁
	
	FLASH_OB_Unlock();   //选项字节区解锁
	if(status == FLASH_COMPLETE)
	{ 

		FLASH->CR |= FLASH_CR_DT1ER;
		FLASH->CR |= FLASH_CR_STRT;	

		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);	

		FLASH->CR &= ~FLASH_CR_DT1ER;
	}	
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status; 
}

/*----------------------------------------------------------------
 * 函数功能：以字的方式对用户数据区进行编程
 * 入口参数：Address,32位Data
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *----------------------------------------------------------------*/
FLASH_Status FLASH_UserData_ProgramWord(uint32_t Address, uint32_t Data)   
{
	/* Check the parameters */
	assert_param(IS_USER_Data_Address(Address));	
	FLASH_Status status = FLASH_COMPLETE;
	uint32_t tmpreg=0;
	
  	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁
	
	FLASH_OB_Unlock();   //选项字节区解锁	
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	
	if(status == FLASH_COMPLETE)
	{
		FLASH->CR |= FLASH_CR_OPTPG;
 
		*(__IO uint32_t*)Address = Data;
		
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);

		FLASH->CR &= ~FLASH_CR_OPTPG;
	}
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status;	
}

/*------------------------------------------------------------------------
 * 函数功能：以半字的方式对用户数据区进行编程
 * 入口参数：Address，16位Data
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *------------------------------------------------------------------------*/
FLASH_Status FLASH_UserData_ProgramHalfWord(uint32_t Address, uint16_t Data)	 
{
	/* Check the parameters */
	assert_param(IS_USER_Data_Address(Address));
	FLASH_Status status = FLASH_COMPLETE;
	uint32_t tmpreg=0;
	
  	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁
	
	FLASH_OB_Unlock();   //选项字节区解锁	
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	
	if(status == FLASH_COMPLETE)
	{
		FLASH->CR |= FLASH_CR_OPTPG; 
		
	   *(__IO uint16_t*)Address = Data;
		
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);

		FLASH->CR &= ~FLASH_CR_OPTPG;
	}
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status;	
}

/*--------------------------------------------------------------------
 * 函数功能：以字节的方式对用户数据区进行编程
 * 入口参数：Address，8位Data
 * 出口参数：None
 * 返回值  ：status
 * 编写日期：
 * 作者    ：
 *--------------------------------------------------------------------*/
FLASH_Status FLASH_UserData_ProgramByte(uint32_t Address, uint8_t Data)
{
	/* Check the parameters */
	assert_param(IS_USER_Data_Address(Address));
	FLASH_Status status = FLASH_COMPLETE;
	uint32_t tmpreg=0;
	
  	tmpreg = VIC_ISER;         //缓存VIC中断使能寄存器初值
    VIC_ICER = 0xFFFFFFFF;     //失能VIC中断
	FLASH_Unlock();//FLASH解锁
	
	FLASH_OB_Unlock();   //选项字节区解锁	
	status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);
	
	if(status == FLASH_COMPLETE)
	{
		FLASH->CR |= FLASH_CR_OPTPG; 
		
	   *(__IO uint8_t*) Address = Data;
		
		status = FLASH_WaitForLastOperation(FLASH_ER_PRG_TIMEOUT);

		FLASH->CR &= ~FLASH_CR_OPTPG;
	}
	FLASH_Lock();	            //FLASH上锁
	FLASH_OB_Lock();            //选项字节区上锁
	VIC_ISER = tmpreg;          //将中断使能初赋给VIC使能寄存器
	return status;
	
}

/*----------------------------------------------------------------
 * 函数功能：FLASH中断配置
 * 入口参数：FLASH_IT，NewState
 *           FLASH_IT： FLASH_CR_EOPIE,FLASH_CR_ERRIE
 * 出口参数：None
 * 返回值  ：None
 * 编写日期：
 * 作者    ：
 *---------------------------------------------------------------*/
void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState)
{
	/* Check the parameters */
	assert_param(IS_FLASH_ITSource(FLASH_IT)); 
    assert_param(IS_FUNCTIONAL_STATE(NewState));
  
    if(NewState != DISABLE)
	{
		FLASH->CR |= FLASH_IT;
	}
	else
	{
		FLASH->CR &= ~FLASH_IT;
    }
	
}

/*--------------------------------------------------
 * 函数功能：读FLASH标志位状态
 * 入口参数：FLASH_Flag
 *           FLASH_Flag: FLASH_Flag_BSY,FLASH_Flag_EOP,FLASH_Flag_PGERR,FLASH_Flag_WRPRTERR
 * 出口参数：None
 * 返回值  ：bitstatus
 * 编写日期：
 * 作者    ：
 *--------------------------------------------------*/
FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_Flag)
{	
	/* Check the parameters */
	assert_param(IS_FLASH_StatusFlag(FLASH_Flag));;
	
	FlagStatus bitstatus = RESET;
	
	if((FLASH->SR & FLASH_Flag) != RESET)
	{
		bitstatus = SET;
	}
	else
	{
		bitstatus = RESET;
	}
	return bitstatus; 
}

/*-----------------------------
 * 函数功能：清零标志位
 * 入口参数：FLASH_Flag
 *           FLASH_Flag: FLASH_Flag_BSY,FLASH_Flag_EOP,FLASH_Flag_PGERR,FLASH_Flag_WRPRTERR
 * 出口参数：None
 * 返回值  ：None
 * 编写日期：
 * 作者    ：
 *------------------------------*/
void FLASH_ClearFlag(uint32_t FLASH_Flag)
{
	/* Check the parameters */
	assert_param(IS_FLASH_ClearFlag(FLASH_Flag));
	FLASH->SR |= FLASH_Flag;
	
}


/****************************END OF FILE****************************/
